package com.zeratul.common.event.core.server.subscribe;

import cn.hutool.core.util.ObjectUtil;
import com.zeratul.common.core.constant.PoolConstants;
import com.zeratul.common.core.context.DataContextHolde;
import com.zeratul.common.event.base.BaseSubscribeServer;
import com.zeratul.common.event.config.prop.ZeratulEventProperties;
import com.zeratul.common.event.core.apply.subscribe.IZtEventHandler;
import com.zeratul.common.event.core.apply.subscribe.ZtEventListener;
import com.zeratul.common.event.domain.ZtEvent;
import com.zeratul.common.event.enums.SubModel;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * 默认的服务层【订阅者】处理器
 */
@Slf4j
public class StandardSubscribeServer implements BaseSubscribeServer {

    /**
     * 注入所有应用层事件处理器
     */
    @Autowired(required = false)
    private List<IZtEventHandler> ztEventHandlers;

    /**
     * 注入线程池
     */
    @Autowired
    @Qualifier(PoolConstants.EVENT_POOL)
    private Executor eventExecutor;

    /**
     * 配置对象
     */
    @Autowired
    private ZeratulEventProperties eventProperties;

    /**
     * 核心服务层处理消息
     */
    @Override
    public <T> void eventHandler(ZtEvent<T> ztEvent) {
        //如果没有消费者，则直接结束
        if (ObjectUtil.isEmpty(ztEventHandlers)) {
            return;
        }

        //执行拦截器
        ztEvent = doInterceptor(ztEvent);
        //如果拦截器返回的消息为null，则终止整个订阅者消费的过程
        if (ObjectUtil.isNull(ztEvent)) {
            return;
        }

        //调用应用层的代码进行消息的实际处理
        for (IZtEventHandler eventHandler : ztEventHandlers) {
            //消息的事件主题
            String topic = ztEvent.getTopic();
            //处理器需要处理的事件类型
            ZtEventListener ztEventListener = eventHandler.getClass().getAnnotation(ZtEventListener.class);
            if (ztEventListener == null) {
                continue;
            }

            //判断事件类型，如果执行器不包含当前事件主题，则直接跳过
            if(!Arrays.asList(ztEventListener.value()).contains(topic)){
                continue;
            }

            // 校验事件处理器的泛型类型是否与事件泛型类型匹配
            if (!isGenericTypeMatch(eventHandler, ztEvent)) {
                log.debug("【事件总线】事件处理器 {} 与事件类型不匹配，跳过处理", eventHandler.getClass().getSimpleName());
                continue;
            }

            //包装成Runnable对象
            Runnable runnable = wrapRunnable(ztEvent, eventHandler);
            //判断是否需要异步执行
            if (ztEventListener.async()) {
                //异步执行
                eventExecutor.execute(runnable);
            } else {
                //同步执行
                runnable.run();
            }

            //判断匹配模式，如果是快速匹配，则直接返回，如果是完整匹配，则继续处理下一个事件处理器
            if (eventProperties.getSubscribe().getSubModel() == SubModel.QUICKLY) {
                return;
            }
        }
    }

    /**
     * 校验事件处理器的泛型类型是否与事件泛型类型匹配
     * @param eventHandler 事件处理器
     * @param ztEvent 事件对象
     * @return 是否匹配
     */
    private <T> boolean isGenericTypeMatch(IZtEventHandler eventHandler, ZtEvent<T> ztEvent) {
        try {
            // 获取事件处理器的泛型类型
            Type[] genericInterfaces = eventHandler.getClass().getGenericInterfaces();
            for (Type genericInterface : genericInterfaces) {
                if (genericInterface instanceof ParameterizedType) {
                    ParameterizedType parameterizedType = (ParameterizedType) genericInterface;
                    // 检查是否实现了IZtEventHandler接口
                    if (parameterizedType.getRawType().getTypeName().equals(IZtEventHandler.class.getName())) {
                        Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                        if (actualTypeArguments.length > 0) {
                            Type handlerType = actualTypeArguments[0];
                            
                            // 获取事件对象的消息类型
                            T msg = ztEvent.getMsg();
                            if (msg == null) {
                                // 如果消息为空，无法确定类型，允许处理
                                return true;
                            }
                            
                            // 比较类型是否匹配或兼容
                            Class<?> msgClass = msg.getClass();
                            if (handlerType instanceof Class) {
                                Class<?> handlerClass = (Class<?>) handlerType;
                                return handlerClass.isAssignableFrom(msgClass);
                            }
                        }
                    }
                }
            }
            
            // 如果无法确定泛型类型，默认允许处理
            return true;
        } catch (Exception e) {
            log.warn("校验事件处理器泛型类型时发生异常: {}", e.getMessage());
            // 发生异常时，默认允许处理
            return true;
        }
    }

    /**
     * 将相关代码封装成Runnable对象
     */
    private <T> Runnable wrapRunnable(ZtEvent<T> target, IZtEventHandler eventHandler) {
        return () -> {
            //获取全局上下文和MCD，设置到当前线程中
            DataContextHolde.setTraceContext(target.getTraceContext());
            MDC.setContextMap(target.getMdc());
            try {
                //当前eventHandler 就是需要处理这个消息的处理器
                eventHandler.doHandler(target.getTopic(), target.getMsg(), target);
            } finally {
                //资源回收
                DataContextHolde.clear();
                MDC.clear();
            }
        };
    }
}